<template>
  <div class="login_container">
    <div class="login_box">
      <!-- 绘制登录框上方logo -->
      <div class="login_logo">
        <img src="../assets/logo.png" class="logo_img" />
      </div>
      <!--表单区域 方法1：不使用通过 prefix-icon 和 suffix-icon 属性，要用到深度选择器/deep/ ::v-deep-->
      <!--<el-form ref="form" :model="form" label-width="0px">
        <el-form-item class="item">
          <i class="el-icon-user-solid icons"></i>
          <el-input v-model="form.name" class="el-input-item"> </el-input>
        </el-form-item>
        <el-form-item class="item">
          <i class="el-icon-lock icons"></i>
          <el-input v-model="form.name" class="el-input-item"></el-input>
        </el-form-item>
        <el-form-item class="item_btn">
          <el-button type="primary" @click="onSubmit">登录</el-button>
          <el-button type="info">重置</el-button>
        </el-form-item>
      </el-form>-->
      <!--表单区域 方法2：使用prefix-icon和suffix-icon属性，在表单中添加前缀和后缀图标-->
      <!-- prop属性，表单域model字段，在使用resetFields和validate时，必须添加,传入的form组件中model字段 -->
      <el-form ref="loginForm" :model="loginForm" :rules="loginFormRules" label-width="0px">
        <el-form-item class="item" prop="username">
          <el-input v-model="loginForm.username" class="el-input-item" prefix-icon="iconfont icon-user"> </el-input>
        </el-form-item>
        <el-form-item class="item" prop="password">
          <el-input v-model="loginForm.password" class="el-input-item" prefix-icon="iconfont icon-3702mima" type="password"> </el-input>
        </el-form-item>
        <el-form-item class="item_btn">
          <el-button type="primary" @click="submitForm('loginForm')">登录</el-button>
          <el-button type="info" @click="resetForm('loginForm')">重置</el-button>
        </el-form-item>
      </el-form>
    </div>
  </div>
</template>

<script>
export default {
  data() {
    return {
      // 数据模型 :model和v-model绑定的
      // 注意：请求路径 login 请求参数username、password,名称必须完全与API文档说明一致
      loginForm: {
        // 调试时，可以把正确的登录用户名和密码直接渲染在登录框中，省去测试时每次登录的过程
        // 另外一个测试账号：admin1/123456
        username: 'admin',
        password: '123456'
      },
      // **要注意：数据模型中的名称要和对应的prop验证规则中名称一致， 否则验证规则将出现混乱
      // 这是表单验证规则对象
      loginFormRules: {
        // 这是验证用户名是否合法
        username: [
          { required: true, message: '请输入登录名称', trigger: 'blur' },
          { min: 3, max: 12, message: '长度在 3 到 12 个字符', trigger: 'blur' }
        ],
        // 这是验证密码是否合法
        password: [
          { required: true, message: '请输入登录密码', trigger: 'blur' },
          {
            min: 6,
            max: 15,
            message: '长度在 6 到 15 个字符',
            trigger: 'blur'
          }
        ]
      }
    };
  },
  methods: {
    // 用户登录表单域的预校验，并向后端发起post请求，提交表单
    submitForm(formName) {
      this.$refs[formName].validate(async valid => {
        if (!valid) return;
        // 测试代码：打印表单中注入的包含用户名和密码的对象
        console.log(this.loginForm);
        /* 第一种写法 */
        // this.$http.post('/login', this.loginForm).then(result => {
        //   console.log(result);
        //   if (result.staus == 200) {
        //     console.log(result.data);
        //   }
        // });
        /* 第二种写法：可以使用await简化promise操作，但是await方法只能用于被async修饰的方法中，
        所以需要在valid前加上async，将匿名函数声明未异步函数 */
        // result数据只有data属性是需要的，将data解构赋值出来,将data起个别名res
        // const data = await this.$http.post('login', this.loginForm);
        // console.log(data);
        // 解构拿到需要的信息，data:{data:{},meta:{}}=data:res
        const { data: res } = await this.$http.post('login', this.loginForm);
        console.log(res);
        if (res.meta.status !== 200) {
          // 登录失败后，显示登录失败消息后，流程就此转向
          return this.$message.error('登录失败！');
        }
        /* 消息提示框方式1：也可以为this.$message({传入对象：包括消息类型和消息提示内容}) */
        // this.$message({
        //   type:'success',
        //   message:'登录成功了哦'
        // });
        this.$message.success('登录成功！');
        // 1.将登录成功之后的token保留在sessionStorage中
        //  1.1 保留token的原因是，基于安全性的考虑，除了登录之外的其他API接口，必须登录之后才能访问
        //  1.2 token只应该在当前网站打开期间生效，所以才将token保存在sessionStorage中而不是localStorage
        // 2.通过编程式导航跳转到后台主页，主页地址是'/home'

        // a.将token保存在会话间的存储sessionStorage中
        sessionStorage.setItem('token', res.data.token);
        // b.编程式导航，发生页面的跳转
        this.$router.push({ name: 'home' });
      });
    },
    // 表单域的重置
    resetForm(formName) {
      this.$refs[formName].resetFields();
    }
  }
};
</script>

<style lang="less" scoped>
.login_container {
  background-color: #2b4b6b;
  height: 100%;
  position: relative;
  .login_box {
    width: 450px;
    height: 300px;
    background-color: #fff;
    border-radius: 3px;
    position: absolute;
    top: 50%;
    left: 50%;
    /* transform属性可以启动css GPU加速，类似还有opacity和filter属性 */
    transform: translate(-50%, -50%);
    .login_logo {
      width: 130px;
      height: 130px;
      box-sizing: border-box;
      background-color: #ffffff;
      border: 10px solid #eeeeee;
      position: absolute;
      left: 50%;
      transform: translateX(-50%);
      top: -65px;
      border-radius: 50%;
      box-shadow: 0 0 10px #dddddd;
      padding: 10px;
      /*.login_logo width:130px;设置padding和border后，分配为内容尺寸+padding+border尺寸，.logo_img width:100%;只能继承content的尺寸(无论是标准盒还是怪异盒，子盒子继承的宽高不包括父盒子的border),
      那么图片宽高应该是90px，为何是110px呢？原因是子盒子相对父盒子定位了，绝对定位子盒子将无视父盒子的padding,以父盒子的border里边界，作为定位基准点  */
      > .logo_img {
        width: 100%;
        height: 100%;
        background-color: #dddddd;
        position: absolute;
        left: 50%;
        top: 50%;
        transform: translate(-50%, -50%);
        border-radius: 50%;
      }
    }
    .el-form {
      margin-top: 114px;
      .item {
        margin: 0 22px 22px 22px;
        /* .el-form-item__content {
         i.icons {
            position: absolute;
            left: 5px;
            top: 50%;
            transform: translateY(-50%);
            color: #ccc;
            font-size: 20px;
            z-index: 99;
          }
          .el-input-item { */
        /* 注意：v-load官网说明，父组件中样式声明了scoped,这个样式不会渗透到子组件中去
            解决办法1：混用.css文件和style声明的样式
            解决办法2：深度选择器，使用>>>操作符
            但是，有些sass、less预处理器不识别 >>> 操作符，这种情况下，可以使用::v-deep 或者 /deep/取而代之，他们都是 <<< 的别名
             */
        /* 方式1：不使用prefix-icon和suffix-icon属性 */
        /*  /v-deep/ input.el-input__inner { */
        /* ::v-deep input.el-input__inner {padding: 0 26px;}} */
        /* 方式2：使用prefix-icon属性和第三方字体图标,在global.scss中声明 */
        /* .el-form-item__content {
          span.el-input__prefix {
            padding: 30px;
            .iconfont {
              font-size: 20px;
            }
          }
        } */
      }
      .item_btn {
        display: flex;
        flex-direction: row;
        justify-content: flex-end;
        margin-right: 22px;
      }
    }
  }
}
</style>
